package cn.itcast.nems.studentrecord.web.controller.b;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.bean.Page;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.common.PageQueryModel;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.util.LocalDateTimeUtils;
import cn.itcast.nems.common.util.NumberUtil;
import cn.itcast.nems.common.web.vo.BasePageRequest;
import cn.itcast.nems.manager.msas.MsasManager;
import cn.itcast.nems.oldems.dto.StudentRecordClazzDTO;
import cn.itcast.nems.studentrecord.api.StudentRecordApi;
import cn.itcast.nems.studentrecord.dao.dataobject.SpecialClazz;
import cn.itcast.nems.studentrecord.dao.dataobject.SpecialClazzQuery;
import cn.itcast.nems.studentrecord.dao.dataobject.StudentRecordFundFlowInfoDO;
import cn.itcast.nems.studentrecord.dao.dataobject.StudentRecordInfoDO;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecordTransaction;
import cn.itcast.nems.studentrecord.dto.StudentRecordDTO;
import cn.itcast.nems.studentrecord.dto.StudentRecordJournalVo;
import cn.itcast.nems.studentrecord.dto.StudentRecordQueryDTO;
import cn.itcast.nems.studentrecord.dto.contract.StudentContractClazzDTO;
import cn.itcast.nems.studentrecord.dto.contract.StudentContractInfoDTO;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordErrorBodyEnum;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordStateEnum;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordContractService;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordFundFlowService;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordService;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordTransactionService;
import cn.itcast.nems.studentrecord.web.util.StudentRecordWebUtil;
import cn.itcast.nems.studentrecord.web.vo.query.StudentRecordPageQueryVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

/**
 * 学籍 controller
 **/
@RestController
@RequestMapping("/b/student")
@RequiredArgsConstructor
@Slf4j
public class StudentRecordController {

    private final StudentRecordApi studentRecordApi;
    private final StudentRecordService studentRecordService;
    private final StudentRecordFundFlowService studentRecordFundFlowService;
    private final StudentRecordTransactionService studentRecordTransactionService;
    private final StudentRecordContractService studentRecordContractService;
    private final MsasManager msasManager;

    @PostMapping("/record/page/list")
    public ResponseEntity<Page<StudentRecordDTO>> findPageList(@RequestBody BasePageRequest<StudentRecordPageQueryVO> queryParam) {
        queryParam.convert();
        PageQueryModel<StudentRecordQueryDTO> queryModel = new PageQueryModel<>(
                queryParam.getPageNumber(),
                queryParam.getPageSize(),
                StudentRecordWebUtil.convert(queryParam.getCondition() == null ? new StudentRecordPageQueryVO() : queryParam.getCondition())
        );
        return ResponseEntity.ok(studentRecordApi.pageQuery(queryModel));
    }

    /**
     * <p>
     * 根据学生ID查询班级列表
     * </p>
     *
     * @param studentId 学员ID
     * @author zhouwei
     * @since 2024/3/11 2:49 PM
     **/
    @GetMapping("/contract/{student_id}/clazz")
    public ResponseEntity<List<StudentContractClazzDTO>> studentClazz(@PathVariable("student_id") String studentId) {
        Assert.isTrue(NumberUtil.checkNum(studentId, null), "学生ID必须为数字");
        List<StudentContractClazzDTO> list = studentRecordContractService.findStudentClazzByStudentId(Integer.valueOf(studentId));
        return ResponseEntity.ok(list);
    }
    /**
     * <p>
     * 获取学籍ID回应的合同
     * </p>
     *
     * @param studentRecordId 学籍ID
     * @param contractNumber 合同编号
     * @author zhouwei
     * @since 2024/4/12 2:40 PM
     **/
    @GetMapping("/contract/url/{student_record_id}/{contract_number}")
    public ResponseEntity<String> getContractUrl(@PathVariable("student_record_id")String studentRecordId , @PathVariable("contract_number") String contractNumber) {
        log.info("【获取学籍ID回应的合同】请求参数 studentRecordId：{}，contractNumber：{}" , studentRecordId,contractNumber  );
        String url  = studentRecordContractService.getContractUrl(studentRecordId , contractNumber );
        Assert.notEmpty(url , BizExceptionProducer.produce(StudentRecordErrorBodyEnum.CONTRACT_NOT_FUND)) ;
        return ResponseEntity.ok(url);
    }

    /**
     * <p>
     * 根据学籍ID查询合同列表
     * </p>
     *
     * @param studentRecordId 学籍ID
     * @author zhouwei
     * @since 2024/3/11 2:54 PM
     **/
    @GetMapping("/contract/clazz/{student_record_id}/contracts")
    public ResponseEntity<List<StudentContractInfoDTO>> studentClazzContracts(@PathVariable("student_record_id") String studentRecordId ) {
        List<StudentContractInfoDTO> list  = studentRecordContractService.findStudentClazzByStudentRecordId(studentRecordId ,null) ;
        return ResponseEntity.ok(list) ;
    }


    /**
     * 功能描述:
     * 1.学籍信息班级列表（含基本信息）
     *
     * @param studentId 学员id
     * @author 陈早庆
     * @update:[变更日期2023年11月30日][更改人姓名][变更描述]
     * @since 2023年11月30日
     */
    @GetMapping("/{studentId}/record")
    public ResponseEntity<List<StudentRecordInfoDO>> listStudentRecordInfo(@PathVariable("studentId") Integer studentId) {
        List<StudentRecordInfoDO> studentRecordInfoDOS = studentRecordService.listStudentRecordInfo(studentId);
        for (StudentRecordInfoDO studentRecordInfoDO : studentRecordInfoDOS) {
            String studentRecordId = studentRecordInfoDO.getId();
//            // 获取支付信息列表
//            List<StudentRecordFundFlowInfoDO> ListStudentRecordFundFlowInfo = studentRecordFundFlowService.listStudentRecordFundFlowInfo(studentRecordId);
//            studentRecordInfoDO.setListStudentRecordFundFlowInfo(ListStudentRecordFundFlowInfo);
            // 进班时间
            LocalDate inDate = LocalDateTimeUtils.parseLocalDate(studentRecordInfoDO.getInDate());
            // 开班时间
            LocalDate startDate = studentRecordInfoDO.getStartDate();
            // 出班时间
            String settlementDate = studentRecordInfoDO.getSettlementDate();
            // 当前所在班级的预计结课日期
            LocalDate predictionGraduationDate = studentRecordInfoDO.getPredictionGraduationDate();
            // 学籍已生效
            String state = studentRecordInfoDO.getState();
            // 进班状态分为：未进班、未开班、已出班、当前就读；
            studentRecordInfoDO.setInClazzState(getInClazzState(startDate, LocalDateTimeUtils.parseLocalDate(settlementDate), state));
            if (settlementDate != null) {
                StudentRecordTransaction studentRecordTransaction = studentRecordTransactionService.selectLastLeaveByStudentRecordId(studentRecordId);
                if (studentRecordTransaction != null) {
                    studentRecordInfoDO.setServiceDays(studentRecordTransaction.getServiceDays());
                    studentRecordInfoDO.setSettlementDays(studentRecordTransaction.getSettlementDays());
                }
            }
        }
        var email = AccountHolder.getRequiredAccountInfo().getEmail();
        var permissions = msasManager.getPermissions(email);
        if (!permissions.contains("student_record_basic_info_record_remark")) {
            log.info("【学籍卡-查询备注】OA邮箱：{} ,没有 student_record_basic_info_record_remark 权限！",email);
            for (StudentRecordInfoDO studentRecordInfoDO : studentRecordInfoDOS) {
                if (studentRecordInfoDO != null)
                    studentRecordInfoDO.setRemark(null);
            }
        }
        return ResponseEntity.ok(studentRecordInfoDOS);
    }

    /**
     * 学籍基本信息
     *
     * @param studentId
     * @param studentRecordId
     * @return
     */
    @GetMapping("/{studentId}/record/{studentRecordId}/details")
    public ResponseEntity<List<StudentRecordInfoDO>> listStudentRecordDetailsInfo(@PathVariable("studentId") Integer studentId, @PathVariable("studentRecordId") String studentRecordId) {
        List<StudentRecordInfoDO> studentRecordInfoDOS = studentRecordService.listStudentRecordInfoByStudentRecordId(studentId, studentRecordId);
        for (StudentRecordInfoDO studentRecordInfoDO : studentRecordInfoDOS) {
            LocalDate startDate = studentRecordInfoDO.getStartDate();
            // 出班时间
            String settlementDate = studentRecordInfoDO.getSettlementDate();
            // 学籍已生效
            String state = studentRecordInfoDO.getState();
            // 进班状态分为：未进班、未开班、已出班、当前就读；
            studentRecordInfoDO.setInClazzState(getInClazzState(startDate, LocalDateTimeUtils.parseLocalDate(settlementDate), state));
        }
        return ResponseEntity.ok(studentRecordInfoDOS);
    }

    /**
     * 获取支付信息列表
     *
     * @param studentId       学生id
     * @param studentRecordId 学籍id
     * @return
     */
    @GetMapping("/{studentId}/record/{studentRecordId}")
    public ResponseEntity<List<StudentRecordFundFlowInfoDO>> listStudentRecordPayInfo(@PathVariable("studentId") Integer studentId, @PathVariable("studentRecordId") String studentRecordId) {
        var result = studentRecordFundFlowService.listStudentRecordFundFlowInfo(studentRecordId);
        var email = AccountHolder.getRequiredAccountInfo().getName();
        var permissions = msasManager.getPermissions(email);
        if (!permissions.contains("student_record_basic_info_record_remark")) {
            for (StudentRecordFundFlowInfoDO studentRecordFundFlowInfoDO : result) {
                if (studentRecordFundFlowInfoDO != null)
                    studentRecordFundFlowInfoDO.setCharge(null);
            }
        }
        return ResponseEntity.ok(result);
    }

    @GetMapping("/{studentId}/record/{studentRecordId}/journals")
    public ResponseEntity<List<StudentRecordJournalVo>> journals(@PathVariable("studentId") Integer studentId, @PathVariable("studentRecordId") String studentRecordId) {
        return ResponseEntity.ok(studentRecordService.journals(studentId, studentRecordId));
    }

    /**
     * 进班状态分为：未进班、未开班、已出班、当前就读；
     *
     * @param startDate      开班时间
     * @param settlementDate 出班时间
     * @param state          学籍状态 StudentRecordStateEnum.VALID.name()
     * @return
     */
    private static String getInClazzState(LocalDate startDate, LocalDate settlementDate, String state) {
        log.info("获取进班状态，请求参数：startDate {}, settlementDate {}, state {}", startDate, settlementDate, state);
        // 当前时间
        LocalDate now = LocalDate.now();
        // 学籍已生效
        Boolean studentRecordState = state.equals(StudentRecordStateEnum.VALID.name());
        Boolean notClazz = Boolean.FALSE;
        Boolean leaveClazz = Boolean.FALSE;
        Boolean startClazz = Boolean.FALSE;
        if (studentRecordState && startDate != null) {
            // 2.未开班：学籍已生效 && 出班时间不存在 && 开班时间不为空 && (当时时间<班级开班时间 || 当时时间=班级开班时间)
            notClazz = (settlementDate == null && (startDate != null && now.isBefore(startDate))) || (settlementDate != null && now.isBefore(startDate) && now.isBefore(settlementDate));

            // 3.已出班：学籍已生效 && 出班时间已存在 && 出班时间不为空 && (出班时间>当时时间 || 出班时间=当时时间)
            leaveClazz = settlementDate != null && (settlementDate.isBefore(now) || settlementDate.isEqual(now));
            // 4.当前就读：“学籍已生效 且 班级开班时间<=当前时间 <=出班时间”或““无出班时间”且“班级开班时间<=当前时间””
            startClazz = (startDate != null && startDate.isBefore(now) || startDate.isEqual(now)
                    && (settlementDate != null && (now.isBefore(settlementDate) || now.isEqual(settlementDate)))
                    || (settlementDate == null && (startDate != null && startDate.isBefore(now) || startDate.isEqual(now))));
        }
        if (!studentRecordState) {
            return "未进班";
        }
        if (notClazz) {
            return "未开班";
        }
        if (leaveClazz) {
            return "已出班";
        }
        if (startClazz) {
            return "当前就读";
        }
        return "未知";
    }

    /**
     * <p>
     * 根据学生ID查学籍关联班级列表
     * </p>
     *
     * @param studentId   学生ID
     * @param upgradeable 是否升级
     * @return 学生ID关联的学籍班级列表
     * @author zhouwei
     * @since 2023/12/14 3:57 PM
     **/
    @GetMapping("/{student_id}/record/clazz")
    public ResponseEntity<List<StudentRecordClazzDTO>> findClazzByStudentId(
            @PathVariable("student_id") Integer studentId,
            @RequestParam(value = "delay_flag", required = false) Boolean delayFlag,
            @RequestParam(value = "upgradeable", required = false) Boolean upgradeable,
            @RequestParam(value = "suspension_flag", required = false) Boolean suspensionFlag
    ) {
        return ResponseEntity.ok(studentRecordService.findClazzByStudentId(
                studentId,
                delayFlag,
                suspensionFlag,
                upgradeable
        ));
    }


    @PostMapping("/special_clazz/{type}/page/list")
    public ResponseEntity<Page<SpecialClazz>> findSpecialClazzPage(@RequestBody cn.itcast.nems.common.BasePageRequest<SpecialClazzQuery> query) {
        return ResponseEntity.ok(studentRecordService.findSpecialClazzPage(query));
    }

    @PostMapping("/special_clazz/{type}/{clazzId}")
    public ResponseEntity<SpecialClazz> findSpecialClazzById(@PathVariable Integer clazzId) {
        return ResponseEntity.ok(studentRecordService.findSpecialClazzById(clazzId));
    }

    @PostMapping("/special_clazz/{type}/search/list")
    public ResponseEntity<Page<SpecialClazz>> searchSpecialClazzList(@RequestBody cn.itcast.nems.common.BasePageRequest<SpecialClazzQuery> query) {
        return ResponseEntity.ok(studentRecordService.findSpecialClazzPage(query));
    }
}
